package com.rw.tool.util.io.file.wrapper;

import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
import com.rw.tool.util.io.file.exception.GetPropDBException;
import com.rw.tool.util.io.file.exception.NotFoundPropertiesDBException;
import com.rw.tool.util.json.CastUtil;
import com.rw.tool.util.json.JsonUtil;
import com.rw.tool.util.string.StringUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;

import java.util.Objects;

/**
 * 查询条件
 */
@Getter
@AllArgsConstructor
public class QueryCondition {
    // 属性名
    private final String property;
    // 比较符号
    private final CompareSign compareSign;
    // 比较值
    private final Object value;

    /**
     * 进行匹配
     *
     * @param data 匹配的对象
     * @return 是否匹配成功
     */
    public boolean match(Object data) {
        // 获取mapper，得到javaType
        ObjectMapper mapper = JsonUtil.getMapper();
        JavaType type = mapper.constructType(data.getClass());

        // 从mapper中取出序列化设置
        SerializationConfig serializationConfig = mapper.getSerializationConfig();
        // 用这个序列化设置解析这个类的信息，找出对应名字的属性
        BeanDescription beanDescription = serializationConfig.introspect(type);
        AnnotatedMethod getter = beanDescription.findProperties()
                .stream()
                .filter(prop -> StringUtil.equals(prop.getName(), property))
                .findAny()
                .orElseThrow(() -> new NotFoundPropertiesDBException("properties " + property + " not found!"))
                .getGetter();

        try {
            // 从对象中获得值，然后进行匹配
            Object targetValue = getter.callOn(data);
            return compare(targetValue, compareSign, value);
        } catch (Exception e) {
            throw new GetPropDBException(e);
        }
    }

    /**
     * 匹配
     */
    private static <T> boolean compare(T left, CompareSign compareSign, T right) {
        // 如果符号为等于，则直接返回两对象是否相等
        if (CompareSign.EQ.equals(compareSign)) {
            return Objects.equals(left, right);
        }

        // 如果符号为like，则判断比较
        if (CompareSign.LIKE.equals(compareSign)) {
            CharSequence leftValue = CastUtil.castObj(left);
            CharSequence rightValue = CastUtil.castObj(right);
            return leftValue != null && leftValue.toString().contains(rightValue);
        }

        // 进行强行转换
        Comparable<T> leftValue = CastUtil.castObj(left);
        int compareResult = leftValue.compareTo(right);

        // 进行比较结果
        if (compareResult > 0) {
            return compareSign == CompareSign.GT || compareSign == CompareSign.GE;
        } else if (compareResult == 0) {
            return compareSign == CompareSign.GE || compareSign == CompareSign.LE;
        } else {
            return compareSign == CompareSign.LT || compareSign == CompareSign.LE;
        }
    }
}
